package hyl.base.flow.dao;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import hyl.base.flow.Flow;
import hyl.base.flow.Link;
import hyl.base.flow.Track;

//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;

import hyl.core.Amy;
import hyl.core.MyFun;
import hyl.core.conf.MyConfig;
import hyl.core.db.Htable;
import hyl.core.db.MyDB;
import hyl.core.db.SelectWhere;
import hyl.core.fun.MyDate2;

/**
 * 必须使用hyl 标准库表 否则无法使用flow 组件
 * 
 * @author 37798955@qq.com
 *
 */
public class HylFlowDao {
	MyDB _db;
	// private static final Logger logger =
	// LoggerFactory.getLogger(FlowMysqlDao.class);

	public HylFlowDao(MyDB db) {
		_db = db;
	}

	public void commit() {
		_db.commit();
	}

	/** 插入流水流水状态 */
	public long insertFlow(Track trk) {
		String value = String.valueOf(trk.getAll());
		int 间隔 = MyDate2.get月间隔();
		String sql1 = "insert into flow(partkey,ctime,mdlname,flowid,track) values(?,now(),?,?,?)";
		Object[] ps = { 间隔, trk.getFlowName(), trk.flowid, value };
		long id = _db.executeUpdate(sql1, ps);
		_db.commit();
		return id;
	}

	public void updateTrack(Track track, Link link) {
		updateTrack(track, link, null);
	}

	/** 更新流水状态 */
	public void updateTrack(Track track, Link link, String 备注) {
		String value = String.valueOf(track.getAll());
		int 间隔 = MyDate2.get月间隔();
		String sql1 = "insert into flow_link(partkey,ctime,lkname,flowid,remark,track) values(?,now(),?,?,?,?)";
		Object[] ps = { 间隔, link.getName(), track.flowid, 备注, value };
		Long id = _db.executeUpdate(sql1, ps);
		sql1 = MyFun.join("update flow set etime=now(),track='", value, "',linkid=", id, " where flowid= '",
				track.flowid, "'");
		_db.executeUpdate(sql1);
		track.linkids.put(link.getName(), id);
		_db.commit();
		// flow_link2 在之后同步插入
	}

	public void appendErrors(Track flow, Link link, Exception e) {
		// logger.info(flow.getFlowName()+' '+link.getName()+e.getMessage());
		String value = String.valueOf(flow.getAll());
		Long linkid = flow.linkids.get(link.getName());
		String sql1 = MyFun.join("update flow set etime=now(),track='", value, "',linkid=", linkid, " where flowid= '",
				flow.flowid, "'");
		_db.executeUpdate(sql1);
		_db.commit();
	}

	// 完成
	public void finish(String flowid) {
		/*
		 * List<String> sqls = new ArrayList<String>(); String sql =
		 * "insert into flow_his (mdlname,flowid,track,ctime,etime)" +
		 * " select  mdlname,flowid,track,ctime,etime from flow where flowid= '" +
		 * flowid + "'"; sqls.add(sql); sql = "delete from flow where flowid= '" +
		 * flowid + "'"; sqls.add(sql); sql =
		 * "insert into flow_link_his (linkid,ctimestamp,flowid,lkname,track)" +
		 * " select linkid,ctimestamp,flowid,lkname,track from flow_link where flowid= '"
		 * + flowid + "'"; sqls.add(sql); sql = "delete from flow_link where flowid= '"
		 * + flowid + "'"; sqls.add(sql); sql = "insert into flow_link2_his " +
		 * " select * from flow_link2 where flowid= '" + flowid + "'"; sqls.add(sql);
		 * sql = "delete from flow_link2 where flowid= '" + flowid + "'"; sqls.add(sql);
		 * _db.batch(sqls);
		 */
	}

	/** 根据流水号 创建特定模型的 流状态 */
	public Track getTrack(String flowid, Flow fm) {
		String sql = "select track from flow where flowid='" + flowid + "'";
		// logger.info(sql);
		String mp = (String) _db.querySingle(sql, null);
		// _db.commit();
		Track tr = new Track(fm, flowid);
		if (!MyFun.isEmpty(mp)) {// 重新载入数据
			tr.setAll(mp);
			String sql1 = "select lkname,linkid from flow_link where flowid=? order by flowid";
			Object[] ps = { flowid };
			List<Map<String, Object>> list = _db.queryList(sql1, ps);
			// _db.commit();
			for (Map<String, Object> m : list) {
				tr.linkids.put((String) m.get("lkname"), (Long) m.get("linkid"));
			}
		} else// 创建一条新的流水
			insertFlow(tr);
		return tr;
	}

	public static void createTables() {
		MyDB db = Amy.createDb();
		List<String> sqls = new ArrayList<String>();
		try {
			MyConfig.loadSql("sql/flow.create", Amy.charset, sqls);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		db.batch(sqls);
	}

////////////////////////////////////账单接口/////////////////////////////////////////		
	public long add用户账单日志(int 会计科目, int A账户类型, int A账户, int B账户类型, int B账户, Long 数额, Long 原账户数额, String 业务编号,
			String 摘要) {
		int 间隔 = MyDate2.get月间隔();
		String sql1 = "insert into bill(partkey,ctime,ymd,s0,i0,i1,i2,i3,i4,l0,l1,flowid,tm0) values(?,now(),DATE_FORMAT(NOW(),'%Y%m%d'),1,?,?,?,?,?,?,?,?,?)";
		Object[] ps = { 间隔, 会计科目, A账户类型, A账户, B账户类型, B账户, 数额, 原账户数额, 业务编号, 摘要 };
		long id = _db.executeUpdate(sql1, ps);
		return id;
	}

	public Map<String, Object> get账单日志(long 账单编号, Integer 分区) {
		SelectWhere sw = new SelectWhere("select *  from  bill where id=");
		sw.append(账单编号).append(" and partkey=", 分区);
		return _db.queryMap(sw.toString(), sw.getSqlParams());
	}

	public Htable get账单日志(String flowid) {
		SelectWhere sw = new SelectWhere("select *  from  bill where flowid=");
		sw.append(flowid);
		return _db.queryHtable(sw.toString(), sw.getSqlParams());
	}

////////////////////////////////////账户接口/////////////////////////////////////////		

	/**
	 * 
	 * @param uid
	 * @param 账户类型 0积分账户 1定期账户 2活动账户 3奖金账户 4提现账户 5押金账户<br>
	 *             10以上的账户是虚拟的外部账户 31微信 32支付宝 33政府账户 34医保账户
	 * @param 数额
	 */
	public Boolean set用户账户数额(int 账户编号, int 账户类型, long 数额) {
		StringBuilder sql1 = new StringBuilder("update account set ctime=now(),l");
		sql1.append(账户类型).append("=l").append(账户类型);
		if (数额 < 0)
			sql1.append(数额);
		else
			sql1.append("+").append(数额);
		sql1.append(" where id=").append(账户编号);
		// MyFun.print(sql1);
		return _db.executeUpdate(sql1.toString());
	}

	public Map<String, Object> get账户(int 账户编号) {
		String sql = MyFun.join("select *  from  account where  id=", 账户编号);
		return _db.queryMap(sql, null);
	}

	public Htable list账户(String 条件) {
		SelectWhere sw = new SelectWhere("select *  from  account  ");
		sw.append("where ", 条件);
		return _db.queryHtable(sw.toString(), null);
	}

	public Boolean set账户数额(int 账户编号, int 子账户, long 数额) {
		StringBuilder sql1 = new StringBuilder("update account set ctime=now(),l");
		sql1.append(子账户).append("=l").append(子账户);
		if (数额 < 0)
			sql1.append(数额);
		else
			sql1.append("+").append(数额);
		sql1.append(" where id=").append(账户编号);
		// MyFun.print(sql1);
		return _db.executeUpdate(sql1.toString());
	}

////////////////////////////////////库存接口/////////////////////////////////////////	

	public Map<String, Object> get库存数额(int 产品编号, Integer 批次, Integer 账户, String 仓库, String 货架, String 货位) {
		SelectWhere sw = new SelectWhere("select i0,i1,ctime from  prod_kc where id=" + 产品编号);
		sw.add("and pcid =?", 批次);
		sw.add("and aid =?", 账户);
		sw.add("and t0 =?", 仓库);
		sw.add("and t1 =?", 货架);
		sw.add("and t2 =?", 货位);
		return _db.queryMap(sw.toString(), sw.getSqlParams());
	}

	public long add库存数额(int 产品编号, Integer 批次, int 数量, Integer 账户, String 仓库, String 货架, String 货位) {
		String sql1 = "insert into prod_kc(ctime,id,pcid,aid,i0,i1,t0,t1,t2) values(now(),?,?,?,0,?,?,?,?)";

		Object[] ps = { 产品编号, MyFun.nvlInt(批次, 0), MyFun.nvlInt(账户, 0), 数量, 仓库, 货架, 货位 };
		return _db.executeUpdate(sql1, ps);
	}

	public long set库存数额(int 产品编号, int 批次, int 数量, int 账户, String 仓库, String 货架, String 储位) {
		StringBuilder sql1 = new StringBuilder("update prod_kc  set ctime=now(),i0=i1,i1=i1");
		if (数量 < 0)
			sql1.append(数量);
		else
			sql1.append("+").append(数量);
		sql1.append(" where id=").append(产品编号);
		SelectWhere sw = new SelectWhere();
		sw.add("and pcid =?", 批次);
		sw.add("and aid =?", 账户);
		sw.add("and t0 =?", 仓库);
		sw.add("and t1 =?", 货架);
		sw.add("and t2 =?", 储位);
		sql1.append(sw.toString());
		// MyFun.print(sql1);
		// MyFun.printJson(sw.getSqlParams());
		return _db.executeUpdate(sql1.toString(), sw.getSqlParams());
	}

////////////////////////////////////临时凭证接口/////////////////////////////////////////
	/*
	 * 凭证关键字 不能超过5
	 */
	public long add临时凭证(Track 足迹, String 说明, Long 原值, Long 变更数量, int[] 凭证关键字) {
		ArrayList<Object> pslist = new ArrayList<Object>();
		pslist.add(足迹.flowid);
		pslist.add(说明);
		pslist.add(原值);
		pslist.add(变更数量);
		StringBuilder sb1 = new StringBuilder("insert into arap(ctime,flowid,tl0,l0,l1");
		StringBuilder sb2 = new StringBuilder(") values(now(),?,?,?,?");
		sb2.append(",").append(原值).append(",").append(变更数量);
		int i = 0;
		for (int j : 凭证关键字) {
			sb1.append(",i").append(i++);
			sb2.append(",?");
			pslist.add(j);
		}
		String sql1 = sb1.toString() + sb2.toString() + ")";
		// MyFun.println(sql1);
		// long id =0;
		return _db.executeUpdate(sql1, pslist.toArray());
	}

	public void del临时凭证(long 业务临时凭证编号) {
		String sql = "delete from  arap where pfid=" + 业务临时凭证编号;
		_db.executeUpdate(sql);

	}

	public void del临时凭证(long[] 业务临时凭证编号) {
		String 编号 = MyFun.join2(",", 业务临时凭证编号);
		String sql = "delete from arap where pfid in (" + 编号 + ")";
		_db.executeUpdate(sql);

	}

	public Map<String, Object> get临时凭证(long 业务临时凭证编号) {
		String sql = "select * from arap where pfid=" + 业务临时凭证编号;
		return _db.queryMap(sql, null);
	}

	public Htable find临时凭证(int[] 凭证关键字) {
		SelectWhere sw = new SelectWhere("select * from arap where 1=1 ");
		for (int i = 0; i < 凭证关键字.length; i++) {
			sw.add("and i" + i + "=?", 凭证关键字[i]);
		}
		return _db.queryHtable(sw.toString(), sw.getSqlParams());
	}

	public Long count临时凭证(int[] 凭证关键字) {
		SelectWhere sw = new SelectWhere("select count(1) num from arap where 1=1 ");
		for (int i = 0; i < 凭证关键字.length; i++) {
			sw.add("and i" + i + "=?", 凭证关键字[i]);
		}
		return MyFun.obj2Long(_db.querySingle(sw.toString(), sw.getSqlParams()));
	}

	public static void main(String[] arg) {
		// HylFlowDao fmd = new HylFlowDao(Amy.getCommitDB1());
		// fmd.set库存数额(1,-23,2,3,null,null,null);
		// fmd.set账户数额(1, 2, 20);
		// fmd.set物流记录(1, 2, 3, null, "", null);
		// fmd.add临时凭证(null, null, null, null, null);
	}
}
